package com.scwatch.ext.service.impl;


import com.scwatch.common.orm.SearchFilter;
import com.scwatch.ext.domain.Advertisement;
import com.scwatch.ext.repository.AdvertisementDao;
import com.scwatch.ext.service.AdvertisementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.Collection;
import java.util.Map;

@Service
@Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
public class AdvertisementServiceImpl implements AdvertisementService{
    @Override
    public Page<Advertisement> findAll(Integer siteId, Map<String, String[]> params, Pageable pageable) {
        return dao.findAll(spec(siteId, params), pageable);
    }

    @Override
    public Advertisement get(Integer id) {

        return dao.findOne(id);
    }

    @Transactional
    public Advertisement save(Advertisement bean) {

        return dao.save(bean);
    }

    @Transactional
    public Advertisement update(Advertisement bean) {

        return dao.save(bean);
    }

    @Transactional
    public Advertisement[] delete(Integer[] ids) {

        if (ids == null) return new Advertisement[0];

        Advertisement[] beans = new Advertisement[ids.length];

        for (int i = 0; i < ids.length; i++) {

            beans[i] = this.delete(ids[i]);
        }
        return beans;
    }

    @Transactional
    public Advertisement delete(Integer id) {

        if (id != null) {

            Advertisement bean = this.get(id);

            return dao.delete(bean);

        }

        return null;
    }

    private Specification<Advertisement> spec(final Integer siteId, Map<String, String[]> params) {

        Collection<SearchFilter> filters = SearchFilter.parse(params).values();

        final Specification<Advertisement> fsp = SearchFilter.spec(filters, Advertisement.class);

        Specification<Advertisement> sp = new Specification<Advertisement>() {

            public Predicate toPredicate(Root<Advertisement> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                Predicate pred = fsp.toPredicate(root, query, cb);

                if (siteId != null) {

                    pred = cb.and(pred, cb.equal(root.get("site").<Integer>get("id"), siteId));

                }

                return pred;

            }
        };
        return sp;
    }

    @Autowired
    private AdvertisementDao dao;
}
